// Copyright (c) 2024, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import "package:expect/expect.dart";
import 'package:expect/variations.dart' as v;

double asDouble(double x) => x; // For the context.

// Constants using no complicated literals.
const minNativeInt = -1 * 65536 * 65536 * 65536 * 32768;
const maxNativeInt = (65536 * 65536 * 65536 * 32 - 1) * 1024;

main() {
  // Integers.
  Expect.equals(1000000000, 1__000_000_000);
  Expect.equals(5558675309, 555_867_5309);
  Expect.equals(-1000000, -1_000_000);
  Expect.equals(100, 00_1_00);
  Expect.equals(-99, -00_99);
  Expect.equals(0, 0__0__0__0__0);

  // Won't parse on the web.
  if (!v.jsNumbers) {
    // 2^63-1, max native int.
    Expect.equals(
      maxNativeInt,
      // == (2^53 - 1) * 2^10 == (65536 * 65536 * 65536 * 32 - 1) * 1024
      0__9__2__2__3__3__7__2__0__3__6__8__5__4__7__7__4__7__8__4,
    );
    // Hexadecimal.
    Expect.equals(
      maxNativeInt,
      // == (2^53 - 1) * 2^10 == (65536 * 65536 * 65536 * 32 - 1) * 1024
      0x0___7__F__F__F__F__F__F__F__F__F__F__F__F__C__0__0,
    );

    // Unsigned large hex literal.
    // TODO(srawlins): Add test cases that can be run on the web and the VM. Something like:
    // 0x0___8__0__0__0___0__0__0___0__0__0__0___0__4__0__0
    // (== -9223372036854775808 == (-65536 * 65536 * 65536 * 32 + 1) * 1025)
    // and
    // 0x0___F__F__F__F___F__F__F__F___F__F__F__F___F__8__0__0
    // (== -2048).
  }
  // Min native int, valid web number, -2^63.
  Expect.equals(
    minNativeInt,
    -0__9__2__2__3__3__7__2__0__3__6__8__5__4__7__7__5__8__0__8,
  );
  Expect.equals(
    minNativeInt,
    -0x0___8__0__0__0___0__0__0__0___0__0__0__0___0__0__0__0,
  );
  // As unsigned literal. Overflows to negative on native.
  Expect.equals(
    v.jsNumbers ? -minNativeInt : minNativeInt,
    0x0___8__0__0__0___0__0__0__0___0__0__0__0___0__0__0__0,
  );

  // Doubles.
  Expect.equals(3.141592653, 3.141_592_653);
  Expect.equals(19.739, 1__9.7_3_9);
  Expect.equals(-1.618, -1.6_1_8);

  Expect.equals(0.0, asDouble(0__0));
  Expect.equals(-0.0, asDouble(-0__0));

  // Exponent notation.
  Expect.equals(1e30, 1e3_0);
  Expect.equals(12e3, 1_2e3);
  Expect.equals(12.34e1, 1_2.3_4e1);

  Expect.equals(0.0, 0__0.0__0);
  Expect.equals(0.0, 0__0e0__0);
  Expect.equals(0.0, 0__0.0__0e0__0);

  // Max finite double as decimal literal.
  Expect.equals(
    1.7976931348623157e+308,
    asDouble(
      0__1__7__9__7__6__9__3__1__3__4__8__6__2__3__1__5__7__0__8__1__4__5__2__7__4__2__3__7__3__1__7__0__4__3__5__6__7__9__8__0__7__0__5__6__7__5__2__5__8__4__4__9__9__6__5__9__8__9__1__7__4__7__6__8__0__3__1__5__7__2__6__0__7__8__0__0__2__8__5__3__8__7__6__0__5__8__9__5__5__8__6__3__2__7__6__6__8__7__8__1__7__1__5__4__0__4__5__8__9__5__3__5__1__4__3__8__2__4__6__4__2__3__4__3__2__1__3__2__6__8__8__9__4__6__4__1__8__2__7__6__8__4__6__7__5__4__6__7__0__3__5__3__7__5__1__6__9__8__6__0__4__9__9__1__0__5__7__6__5__5__1__2__8__2__0__7__6__2__4__5__4__9__0__0__9__0__3__8__9__3__2__8__9__4__4__0__7__5__8__6__8__5__0__8__4__5__5__1__3__3__9__4__2__3__0__4__5__8__3__2__3__6__9__0__3__2__2__2__9__4__8__1__6__5__8__0__8__5__5__9__3__3__2__1__2__3__3__4__8__2__7__4__7__9__7__8__2__6__2__0__4__1__4__4__7__2__3__1__6__8__7__3__8__1__7__7__1__8__0__9__1__9__2__9__9__8__8__1__2__5__0__4__0__4__0__2__6__1__8__4__1__2__4__8__5__8__3__6__8,
    ),
  );

  Expect.equals(
    1.7976931348623157e+308,
    0__1__7__9__7__6__9__3__1__3__4__8__6__2__3__1__5__7__0__8__1__4__5__2__7__4__2__3__7__3__1__7__0__4__3__5__6__7__9__8__0__7__0__5__6__7__5__2__5__8__4__4__9__9__6__5__9__8__9__1__7__4__7__6__8__0__3__1__5__7__2__6__0__7__8__0__0__2__8__5__3__8__7__6__0__5__8__9__5__5__8__6__3__2__7__6__6__8__7__8__1__7__1__5__4__0__4__5__8__9__5__3__5__1__4__3__8__2__4__6__4__2__3__4__3__2__1__3__2__6__8__8__9__4__6__4__1__8__2__7__6__8__4__6__7__5__4__6__7__0__3__5__3__7__5__1__6__9__8__6__0__4__9__9__1__0__5__7__6__5__5__1__2__8__2__0__7__6__2__4__5__4__9__0__0__9__0__3__8__9__3__2__8__9__4__4__0__7__5__8__6__8__5__0__8__4__5__5__1__3__3__9__4__2__3__0__4__5__8__3__2__3__6__9__0__3__2__2__2__9__4__8__1__6__5__8__0__8__5__5__9__3__3__2__1__2__3__3__4__8__2__7__4__7__9__7__8__2__6__2__0__4__1__4__4__7__2__3__1__6__8__7__3__8__1__7__7__1__8__0__9__1__9__2__9__9__8__8__1__2__5__0__4__0__4__0__2__6__1__8__4__1__2__4__8__5__8__3__6__8.0__0,
  );

  Expect.equals(
    1.7976931348623157e+308,
    0__1__7__9__7__6__9__3__1__3__4__8__6__2__3__1__5__7__0__8__1__4__5__2__7__4__2__3__7__3__1__7__0__4__3__5__6__7__9__8__0__7__0__5__6__7__5__2__5__8__4__4__9__9__6__5__9__8__9__1__7__4__7__6__8__0__3__1__5__7__2__6__0__7__8__0__0__2__8__5__3__8__7__6__0__5__8__9__5__5__8__6__3__2__7__6__6__8__7__8__1__7__1__5__4__0__4__5__8__9__5__3__5__1__4__3__8__2__4__6__4__2__3__4__3__2__1__3__2__6__8__8__9__4__6__4__1__8__2__7__6__8__4__6__7__5__4__6__7__0__3__5__3__7__5__1__6__9__8__6__0__4__9__9__1__0__5__7__6__5__5__1__2__8__2__0__7__6__2__4__5__4__9__0__0__9__0__3__8__9__3__2__8__9__4__4__0__7__5__8__6__8__5__0__8__4__5__5__1__3__3__9__4__2__3__0__4__5__8__3__2__3__6__9__0__3__2__2__2__9__4__8__1__6__5__8__0__8__5__5__9__3__3__2__1__2__3__3__4__8__2__7__4__7__9__7__8__2__6__2__0__4__1__4__4__7__2__3__1__6__8__7__3__8__1__7__7__1__8__0__9__1__9__2__9__9__8__8__1__2__5__0__4__0__4__0__2__6__1__8__4__1__2__4__8__5__8__3__6__8e0__0,
  );

  Expect.equals(
    1.7976931348623157e+308,
    0__1__7__9__7__6__9__3__1__3__4__8__6__2__3__1__5__7__0__8__1__4__5__2__7__4__2__3__7__3__1__7__0__4__3__5__6__7__9__8__0__7__0__5__6__7__5__2__5__8__4__4__9__9__6__5__9__8__9__1__7__4__7__6__8__0__3__1__5__7__2__6__0__7__8__0__0__2__8__5__3__8__7__6__0__5__8__9__5__5__8__6__3__2__7__6__6__8__7__8__1__7__1__5__4__0__4__5__8__9__5__3__5__1__4__3__8__2__4__6__4__2__3__4__3__2__1__3__2__6__8__8__9__4__6__4__1__8__2__7__6__8__4__6__7__5__4__6__7__0__3__5__3__7__5__1__6__9__8__6__0__4__9__9__1__0__5__7__6__5__5__1__2__8__2__0__7__6__2__4__5__4__9__0__0__9__0__3__8__9__3__2__8__9__4__4__0__7__5__8__6__8__5__0__8__4__5__5__1__3__3__9__4__2__3__0__4__5__8__3__2__3__6__9__0__3__2__2__2__9__4__8__1__6__5__8__0__8__5__5__9__3__3.2__1__2__3__3__4__8__2__7__4__7__9__7__8__2__6__2__0__4__1__4__4__7__2__3__1__6__8__7__3__8__1__7__7__1__8__0__9__1__9__2__9__9__8__8__1__2__5__0__4__0__4__0__2__6__1__8__4__1__2__4__8__5__8__3__6__8e0__6__7,
  );

  Expect.equals(
    1.7976931348623157e+308,
    0__1__7__9__7__6__9__3__1__3__4__8__6__2__3__1__5__7__0__8__1__4__5__2__7__4__2__3__7__3__1__7__0__4__3__5__6__7__9__8__0__7__0__5__6__7__5__2__5__8__4__4__9__9__6__5__9__8__9__1__7__4__7__6__8__0__3__1__5__7__2__6__0__7__8__0__0__2__8__5__3__8__7__6__0__5__8__9__5__5__8__6__3__2__7__6__6__8__7__8__1__7__1__5__4__0__4__5__8__9__5__3__5__1__4__3__8__2__4__6__4__2__3__4__3__2__1__3__2__6__8__8__9__4__6__4__1__8__2__7__6__8__4__6__7__5__4__6__7__0__3__5__3__7__5__1__6__9__8__6__0__4__9__9__1__0__5__7__6__5__5__1__2__8__2__0__7__6__2__4__5__4__9__0__0__9__0__3__8__9__3__2__8__9__4__4__0__7__5__8__6__8__5__0__8__4__5__5__1__3__3__9__4__2__3__0__4__5__8__3__2__3__6__9__0__3__2__2__2__9__4__8__1__6__5__8__0__8__5__5__9__3__3__2__1__2__3__3__4__8__2__7__4__7__9__7__8__2__6__2__0__4__1__4__4__7__2__3__1__6__8__7__3__8__1__7__7__1__8__0__9__1__9__2__9__9__8__8__1__2__5__0__4__0__4__0__2__6__1__8__4__1__2__4__8__5__8__3__6__8__0__0__0__0__0__0__0__0__0__0__0__0e-0__1__2,
  );

  Expect.equals(double.infinity, 2e3__0__8);
  Expect.equals(double.infinity, 2__0__0e3__0__6);
  Expect.equals(double.infinity, 0__1.9__1e3__0__8);

  // Coerced number.
  double a = 1_000;
  Expect.equals(1000.0, a);

  // Constant numbers.
  const b = 2_000;
  Expect.equals(2000, b);
  const c = 3_000.3_000;
  Expect.equals(3000.3000, c);
  const double d = 4_000;
  Expect.equals(4000, d);
}
